package com.jweb.framework.ws.client;

import java.util.Map;
import javax.xml.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.util.Assert;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.transport.WebServiceMessageSender;
import com.jweb.framework.core.channel.CommunicationException;
import com.jweb.framework.core.channel.Gateway;
import com.jweb.framework.ws.channel.QNameMapping;
import com.jweb.framework.ws.channel.ServiceManager;
import com.jweb.framework.ws.channel.ServiceManagerAware;
import com.jweb.framework.ws.soap.addressing.client.WSAddressingHead;

/**
 * 修改人： Thomas
 * 修改内容：新增 
 * 类说明：通过 spring-ws 统一调用第三方服务
 */
public class WebServiceGateway implements Gateway , ServiceManagerAware , InitializingBean {
	
	protected final Log log = LogFactory.getLog(WebServiceGateway.class);
	private ServiceManager serviceManager ;
	private WebServiceTemplateJWeb webServiceTemplateJKurrent ;
	private QNameMapping identityMapping ;
	private String identityName ;
	private Unmarshaller unmarshaller ;
	private Marshaller marshaller ;
	private TargetURIMapping targetURIMapping ;
	
	public void setTargetURIMapping(TargetURIMapping targetURIMapping){
		this.targetURIMapping = targetURIMapping ;
	}
	
	public WebServiceGateway(WebServiceMessageFactory webServiceMessageFactory){
		this.identityName = "TransCode";
		this.webServiceTemplateJKurrent = new WebServiceTemplateJWeb(webServiceMessageFactory);
	}
	
	public void setUnmarshaller(Unmarshaller unmarshaller){
		this.unmarshaller = unmarshaller ;
		this.webServiceTemplateJKurrent.setUnmarshaller(unmarshaller);
		if(unmarshaller instanceof Marshaller){
			this.marshaller = (Marshaller) unmarshaller ;
			this.webServiceTemplateJKurrent.setMarshaller(this.marshaller);
		}
	}
	
	public void setMarshaller(Marshaller marshaller){
		this.marshaller = marshaller ;
		this.webServiceTemplateJKurrent.setMarshaller(marshaller);
		if(marshaller instanceof Unmarshaller){
			this.unmarshaller = (Unmarshaller) marshaller ;
			this.webServiceTemplateJKurrent.setUnmarshaller(this.unmarshaller);
		}
	}
	
	public void setIdentityName(String s){
		this.identityName = s ;
	}
	
	public void setServiceManager(ServiceManager serviceManager){
		this.serviceManager = serviceManager ;
	}
	
	public void setIdentityMapping(QNameMapping qn){
		this.identityMapping = qn;
	}
	
	public final void setDefaultUri(String uri){
		this.webServiceTemplateJKurrent.setDefaultUri(uri);
	}
	
	public final void setMessageSender(WebServiceMessageSender webServiceMessageSender){
		this.webServiceTemplateJKurrent.setMessageSender(webServiceMessageSender);
	}
	
	public final void setMessageSenders(WebServiceMessageSender webServiceMessageSenders[]){
		this.webServiceTemplateJKurrent.setMessageSenders(webServiceMessageSenders);
	}
	
	public final void setInterceptors(ClientInterceptor clientInterceptors[]){
		this.webServiceTemplateJKurrent.setInterceptors(clientInterceptors);
	}
	
	public final void afterPropertiesSet() throws Exception {
		Assert.notNull(this.identityMapping , "'identityMapping' must not be null. ");
		Assert.notNull(this.marshaller , "'marshaller ' must not be null.");
		Assert.notNull(this.unmarshaller , "'unmarshaller' must not be null.");
		this.webServiceTemplateJKurrent.afterPropertiesSet();
		
	}
	
	public Object send(Object obj , String s) throws CommunicationException {
		
		throw new UnsupportedOperationException();
		
	}
	
	public Object receive(Object obj , String s) throws CommunicationException {
		throw new UnsupportedOperationException() ;
	}
	
	public Object sendAndReceive(Object obj , String s) throws CommunicationException {
		
		Map map = (Map) obj ;
		if(log.isDebugEnabled()){
			log.info((new StringBuffer("@@@@request data : ")).append(map).toString());
		}
		
		s = (String) map.get(this.identityName);
		if(s == null){
			throw new IllegalStateException((new StringBuilder("No identity found use name:")).append(this.identityName).toString());
		}
		
		QName qname = this.identityMapping.toQName(s);
		if(qname == null){
			throw new IllegalStateException((new StringBuilder("No QName mapped by QNameMapping for ")).append(s).toString());
		}
		
		String s1 = null ;
		if(this.targetURIMapping != null){
			s1 = this.targetURIMapping.getTargetURI(s , map);
		}
		
		if(s1 == null){
			s1 = invoke(qname);
		}
		
		
		map.put("QNameMapping.current", qname);
		boolean flag = this.serviceManager.isOneway(qname);
		boolean flag1 = this.serviceManager.isUseAddressing(qname);
		WSAddressingHead wsAddressingHead = this.serviceManager.getWsAddressingHead(qname);
		
		// 目前对SOAP头信息不处理
		//ActionCallback actionCallback = null ;
		
		/*if(flag1){ // false
			String s2 = wsAddressingHead.getAction();
			String s3 = qname.getLocalPart();
			String s4 = s2.endsWith("/")?(new StringBuilder(String.valueOf(s2))).append(s3).toString() : (new StringBuilder(String.valueOf(s2))).append("/").append("/").append(s3).toString();
			String s5 = wsAddressingHead.getFrom();
			String s6 = wsAddressingHead.getTo();
			try {
				actionCallback = new ActionCallback(s4 , s5 , s6);
			} catch (URISyntaxException e) {
				throw new IllegalStateException("illegal ws-addressing's action");
			}
		}*/
		
		// 此分支没有实现，可以根据需要在WebServiceTemplateJKurrent类中实现如下两个方法
		/*if(flag){ 
			if(s1 == null){	
				this.webServiceTemplateJKurrent.marshalSend(map , actionCallback);
			}
			else {
				this.webServiceTemplateJKurrent.marshalSend(s1 , map , actionCallback);
			}
		}*/
		
		/*Map rspMap = ((s1 != null) ? this.webServiceTemplateJKurrent.marshalSendAndReceive(s1 , map , actionCallback)
								   : this.webServiceTemplateJKurrent.marshalSendAndReceive(map , actionCallback));*/
		
		Map rspMap = (Map) ((s1 != null) ? this.webServiceTemplateJKurrent.marshalSendAndReceive(s1 , map , null)
				   : this.webServiceTemplateJKurrent.marshalSendAndReceive(map , null));
		
		if(rspMap == null){
			throw new CommunicationException(true);
		}
		
		return rspMap ;
	}
	
	private String invoke(QName qname){
		String s = this.serviceManager.getLocation(qname);
		if(log.isDebugEnabled()){
			log.debug((new StringBuilder("send uri: ")).append(s!=null ? s : this.webServiceTemplateJKurrent.getDefaultUri()).toString());
		}
		
		return s ;
	}

	/*public void setServiceManager() {
		
		
	}*/
	
}
